package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidAlbum;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.user.mapper.UserInfoMapper;
import com.atguigu.tingshu.user.mapper.UserPaidAlbumMapper;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.service.UserPaidTrackService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private WxMaService wxMaService;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private RabbitService rabbitService;


	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;

	@Autowired
	private  UserPaidTrackService userPaidTrackService;

	@Override
	public boolean isPaidAlbum(Long albumId, Long userId) {
		//	albumId userId 在表中有且只有一条记录
		return userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getAlbumId, albumId).eq(UserPaidAlbum::getUserId, userId)) != null;
	}

	// 获取用户已购的音频
	@Override
	public Map<Long, Integer> getPaiedTrack(Long albumId, Long userId, List<Long> trackIdList) {
		/*//现在我们远程调用的那块需要用到的是，用于已经购买了 的专辑和声音
		//获取用户购买专辑对象
		HashMap<Long, Integer> map = new HashMap<>();
		LambdaQueryWrapper<UserPaidAlbum> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(UserPaidAlbum::getUserId,userId).eq(UserPaidAlbum::getAlbumId,albumId);

		UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(wrapper);
		if(null!=userPaidAlbum){
			//用户购买了

			for (Long trackId : trackIdList) {
				map.put(trackId,1);
			}
			return map;
		}else {
			//对象为空，说明没有买过专辑，但是可能也会买过专辑下对应的某个声音
			//根据用户id获取用户买过的声音
			LambdaQueryWrapper<UserPaidTrack> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.eq(UserPaidTrack::getUserId,userId).in(UserPaidTrack::getTrackId,trackIdList);
			//用户购买声音记录
			List<UserPaidTrack> list = userPaidTrackService.list(queryWrapper);

			//声音id集合
			List<Long> collect = list.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
			for (Long trackId : collect) {
				if(list.contains(trackId)){
					map.put(trackId,1);
				}else{
					map.put(trackId,0);
				}
			}
			return map;
		}*/
		//	根据UserId,albumId 获取到用户付款专辑对象
		LambdaQueryWrapper<UserPaidAlbum> userPaidAlbumLambdaQueryWrapper = new LambdaQueryWrapper<>();
		userPaidAlbumLambdaQueryWrapper.eq(UserPaidAlbum::getUserId,userId).eq(UserPaidAlbum::getAlbumId,albumId);
		UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(userPaidAlbumLambdaQueryWrapper);
		//	判断
		if (null != userPaidAlbum){
			//	创建一个map 集合
			HashMap<Long, Integer> map = new HashMap<>();
			//	如果查询到对应的专辑购买记录，则默认将声音Id 赋值为 1
			trackIdList.forEach(trackId->{
				map.put(trackId,1);
			});
			return map;
		} else {
			//	根据用户Id 与专辑Id 查询用户购买声音记录
			LambdaQueryWrapper<UserPaidTrack> userPaidTrackLambdaQueryWrapper = new LambdaQueryWrapper<>();
			userPaidTrackLambdaQueryWrapper.eq(UserPaidTrack::getUserId,userId).in(UserPaidTrack::getTrackId,trackIdList);
			List<UserPaidTrack> userPaidTrackList = userPaidTrackService.list(userPaidTrackLambdaQueryWrapper);
			//	获取到用户购买声音Id 集合
			List<Long> userPaidTrackIdList = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
			//	创建一个map 集合
			HashMap<Long, Integer> map = new HashMap<>();
			trackIdList.forEach(trackId ->{
				if (userPaidTrackIdList.contains(trackId)){
					//	用户已购买声音
					map.put(trackId,1);
				}else {
					map.put(trackId,0);
				}
			});
			return map;
		}
	}

	@Override
	public void updateUser(UserInfoVo userInfoVo, Long userId) {
		//	更新用户信息
		UserInfo userInfo = new UserInfo();
		userInfo.setId(userId);
		userInfo.setNickname(userInfoVo.getNickname());
		userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());
		this.userInfoMapper.updateById(userInfo);
	}
	@Override
	public UserInfoVo getUserInfoVoByUserId(Long userId) {
		//	获取到用户信息对象
		UserInfo userInfo = this.getById(userId);
		//	创建UserInfoVo 对象
		UserInfoVo userInfoVo = new UserInfoVo();
		//	属性拷贝
		BeanUtils.copyProperties(userInfo,userInfoVo);
		return userInfoVo;
	}

	/**
	 * 微信登录
	 * @param code
	 */
	@SneakyThrows
	@Override
	public Map<String, Object> wxLogin(String code) {
		/*log.info("微信登录：code:{}",code);
		WxMaJscode2SessionResult wxMaJscode2SessionResult = waService.jsCode2SessionInfo(code);
		//获取用户的唯一标识
		String openid = wxMaJscode2SessionResult.getOpenid();
		//在数据库中查询这个openid是否存在,因为openid是用户的唯一标识,所以
		UserInfo userInfo = getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));

		// 判断是否是第一次登录
		if(userInfo==null){
			//说明是第一次登录，需要注册
			userInfo = new UserInfo();
			//对注册的新用户进行赋值
			userInfo.setWxOpenId(openid);
			//  赋值用户昵称
			userInfo.setNickname("听友"+System.currentTimeMillis());
			//  赋值用户头像图片
			userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");

			//保存用户
			this.save(userInfo);

			//锁客操作，为当前注册用户赠送1000元,就要用到远程调用和消息队列
			//给用户账户模块发送普通消息
			//发送的消息是当前的用户Id，发送的消息由消费者决定，因为我们对于用户账户模块，只需要知道当前用户Id即可
			rabbitService.sendMessage(MqConst.EXCHANGE_USER,MqConst.ROUTING_USER_REGISTER,userInfo.getId());

		}
		//说明用户不是第一次登录，我们要将登录成功的用户信息保存到redis中,生成一个token
		String token = UUID.randomUUID().toString().replace("-","");
		//从redis中获取用户信息
		//登录了，但是token是否正确，需要从redis中获取token，判断是否一致，如果不一致，说明token已经过期，需要重新登录
		String userLoginToken = RedisConstant.USER_LOGIN_KEY_PREFIX+token;
		this.redisTemplate.opsForValue().set(userLoginToken,userInfo,RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);

		//创建一个map将map返回给前端
		Map<String, String> map = new HashMap<>();
		map.put("token",token);
		return map;*/
		//	调用服务方法
		WxMaJscode2SessionResult wxMaJscode2SessionResult = null;
		try {
			wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(code);
		} catch (WxErrorException e) {
			throw new RuntimeException(e);
		}
		//	获取openid;
		String openId = wxMaJscode2SessionResult.getOpenid();
		//	使用 openid 查询数据库，判断用户是否已经注册
		UserInfo userInfo = this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openId));
		//	判断
		if (null == userInfo){
			//	当前没有注册过;
			userInfo = new UserInfo();
			userInfo.setWxOpenId(openId);
			userInfo.setNickname("听友:"+System.currentTimeMillis());
			userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
			//	保存数据
			this.save(userInfo);
			//	注册就送钱! 1000块; openFeignClient; 发送消息; 发送的内容是由消费者决定的！
			rabbitService.sendMessage(MqConst.EXCHANGE_USER,MqConst.ROUTING_USER_REGISTER,userInfo.getId());

		}
		//	直接返回登录成功！
		String token = UUID.randomUUID().toString().replaceAll("-","");
		//  从缓存中获取数据
		String userLoginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
		this.redisTemplate.opsForValue().set(userLoginKey,userInfo,RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
		//	创建Map 集合
		Map<String,Object> map = new HashMap<>();
		map.put("token",token);
		//	返数据
		return map;
	}
}
